package com.goodboys.base.filter;

import com.alibaba.fastjson.JSON;
import com.goodboys.base.resp.ErrorMsgEnum;
import com.goodboys.base.resp.Response;
import com.goodboys.base.utils.RedisClient;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

/**
 * Created by CJ on 2018-05-01.
 */

/*@Order(1)
@Component
@WebFilter(filterName = "jwtFilter", urlPatterns = {"/user*//*","/info*//*","/tag*//*","/comment*//*"})*/
public class JwtFilter extends GenericFilterBean{

    @Autowired
    private RedisClient redisClient;

    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain)
            throws IOException, ServletException {

        // Change the req and res to HttpServletRequest and HttpServletResponse
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

       /* ServletContext sc = request.getSession().getServletContext();
        XmlWebApplicationContext cxt = (XmlWebApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc);

        if(cxt != null && cxt.getBean("redisClient") != null && redisClient == null){
             redisClient = (RedisClient) cxt.getBean("redisClient");
        }*/

        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // Get authorization from Http request
        final String authHeader = request.getHeader("authorization");


        // If the Http request is OPTIONS then just return the status code 200
        // which is HttpServletResponse.SC_OK in this code
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(req, res);
        }
        // Except OPTIONS, other request should be checked by JWT
        else {
            // Check the authorization, check if the token is started by "Bearer "
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                if("GET".equals(request.getMethod()))
                    request.getRequestDispatcher("/sys/error?message=请先登录。。。").forward(request, response);
                else
                    request.getRequestDispatcher("/sys/postError?message=请先登录。。。").forward(request, response);
                logger.warn("请先登录。。。");
                return;
            }

            // Then get the JWT token from authorization
            final String token = authHeader.substring(7);

            try {
                // Use JWT parser to check if the signature is valid with the Key "secretkey"
                final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();

                //判断该用户信息是否正确

                //token设置失效时间，需要重新登录
                try {
                    if (!redisClient.isExistKey("token:"+authHeader)) {
                        if("GET".equals(request.getMethod()))
                            request.getRequestDispatcher("/sys/error?message=登录信息过期，请重新登录。。。").forward(request, response);
                        else
                            request.getRequestDispatcher("/sys/postError?message=登录信息过期，请重新登录。。。").forward(request, response);
                        logger.warn("登录过期，请重新登录。。。");
                        return;
                    }
                } catch (NullPointerException e) {
                    e.printStackTrace();
                }
                /*Integer times = Math.toIntExact(new Date().getTime() / 1000);
                Integer back = (Integer) claims.get("iat");
                if ((times - back )  / 3600 / 24 > 7){
                    request.getRequestDispatcher("/sys/error?message=登录信息过期，请重新登录。。。").forward(request, response);
                    logger.warn("登录过期，请重新登录。。。");
                    return;
                }*/

                // Add the claim to request header
                request.setAttribute("claims", claims);

            } catch (final SignatureException e) {
                if("GET".equals(request.getMethod()))
                    request.getRequestDispatcher("/sys/error?message=登录信息有误。。。").forward(request, response);
                else
                    request.getRequestDispatcher("/sys/postError?message=登录信息有误。。。").forward(request, response);
                logger.warn("登录信息有误。。。");
                return;
            }
            chain.doFilter(req, res);
        }
    }
}
